using System;
using System.Collections.Generic;
using System.Linq;

namespace TXK
{
    /// <summary>
    /// 位转换库
    /// </summary>
    public class BitLib
    {
        /// <summary>
        /// 返回指定字节的指定位
        /// </summary>
        /// <param name="b">字节</param>
        /// <param name="offset">指定位（0-7）</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFromByte(byte b, int offset)
        {
            if (offset >= 0 && offset <= 7)
            {
                return (b & (int)Math.Pow(2.0, offset)) != 0;
            }
            throw new Exception("索引必须为0-7之间");
        }

        /// <summary>
        /// 返回字节数组中的某个字节某个位
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="index">字节索引</param>
        /// <param name="offset">指定位（0-7）</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFromByteArray(byte[] b, int index, int offset)
        {
            byte byteFromByteArray = ByteLib.GetByteFromByteArray(b, index);
            return GetBitFromByte(byteFromByteArray, offset);
        }

        /// <summary>
        /// 返回两个字节的指定位
        /// </summary>
        /// <param name="b">两个字节</param>
        /// <param name="offset">指定位（0-15）</param>
        /// <param name="reverse">字节顺序</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFrom2Byte(byte[] b, int offset, bool reverse = false)
        {
            byte b2 = (reverse ? b[0] : b[1]);
            byte b3 = (reverse ? b[1] : b[0]);
            if (offset >= 0 && offset <= 7)
            {
                return GetBitFromByte(b3, offset);
            }
            if (offset >= 8 && offset <= 15)
            {
                return GetBitFromByte(b2, offset - 8);
            }
            throw new Exception("索引必须为0-15之间");
        }

        /// <summary>
        /// 返回字节数组中某2个字节的指定位
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="index">字节索引</param>
        /// <param name="offset">指定位（0-15）</param>
        /// <param name="reverse">字节顺序</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFrom2ByteArray(byte[] b, int index, int offset, bool reverse = false)
        {
            byte[] byteArray = ByteArrayLib.GetByteArray(b, index, 2);
            if (byteArray != null)
            {
                return GetBitFrom2Byte(byteArray, offset, reverse);
            }
            throw new Exception("请检查字节索引");
        }

        /// <summary>
        /// 根据一个Short返回指定位
        /// </summary>
        /// <param name="val">short数值</param>
        /// <param name="offset">指定位（0-15）</param>
        /// <param name="reverse">字节顺序</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFromShort(short val, int offset, bool reverse = false)
        {
            return GetBitFrom2Byte(BitConverter.GetBytes(val), offset, reverse);
        }

        /// <summary>
        /// 根据一个UShort返回指定位
        /// </summary>
        /// <param name="val">ushort数值</param>
        /// <param name="offset">指定位（0-15）</param>
        /// <param name="reverse">字节顺序</param>
        /// <returns>布尔结果</returns>
        public static bool GetBitFromUShort(ushort val, int offset, bool reverse = false)
        {
            return GetBitFrom2Byte(BitConverter.GetBytes(val), offset, reverse);
        }

        /// <summary>
        /// 将一个字节转换成布尔数组
        /// </summary>
        /// <param name="b">字节</param>
        /// <param name="reverse">位顺序</param>
        /// <returns>布尔数组</returns>
        public static bool[] GetBitArrayFromByte(byte b, bool reverse = false)
        {
            bool[] array = new bool[8];
            if (reverse)
            {
                for (int num = 7; num >= 0; num--)
                {
                    array[num] = (b & 1) == 1;
                    b = (byte)(b >> 1);
                }
            }
            else
            {
                for (int i = 0; i <= 7; i++)
                {
                    array[i] = (b & 1) == 1;
                    b = (byte)(b >> 1);
                }
            }
            return array;
        }

        /// <summary>
        /// 将一个字节数组转换成布尔数组
        /// </summary>
        /// <param name="b">字节数组</param>
        /// <param name="reverse">位顺序</param>
        /// <returns>布尔数组</returns>
        public static bool[] GetBitArrayFromByteArray(byte[] b, bool reverse = false)
        {
            List<bool> list = new List<bool>();
            foreach (byte b2 in b)
            {
                list.AddRange(GetBitArrayFromByte(b2, reverse));
            }
            return list.ToArray();
        }

        /// <summary>
        /// 根据位开始和长度截取位数组
        /// </summary>
        /// <param name="source"></param>
        /// <param name="start"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static bool[] GetBitArray(bool[] source, int start, int length)
        {
            bool[] array = new bool[length];
            if (source != null && start >= 0 && length > 0 && source.Length >= start + length)
            {
                Array.Copy(source, start, array, 0, length);
                return array;
            }
            return null;
        }

        /// <summary>
        /// 将字符串按照指定的分隔符转换成布尔数组
        /// </summary>
        /// <param name="val"></param>
        /// <param name="spilt"></param>
        /// <returns></returns>
        public static bool[] GetBitArrayFromBitArrayString(string val, char spilt = ' ')
        {
            val = val.Trim();
            List<bool> list = new List<bool>();
            if (val.Contains(spilt))
            {
                string[] array = val.Split(new char[1] { spilt }, StringSplitOptions.RemoveEmptyEntries);
                string[] array2 = array;
                foreach (string text in array2)
                {
                    list.Add(text.Trim().ToLower() == "true" || text.Trim().ToLower() == "1");
                }
            }
            else
            {
                list.Add(val.Trim().ToLower() == "true" || val.Trim().ToLower() == "1");
            }
            return list.ToArray();
        }

        public static bool[] ByteToBoolArray(byte[] InBytes, int length)
        {
            if (InBytes == null)
            {
                return null;
            }
            if (length > InBytes.Length * 8)
            {
                length = InBytes.Length * 8;
            }
            bool[] array = new bool[length];
            for (int i = 0; i < length; i++)
            {
                int num = i / 8;
                int num2 = i % 8;
                byte b = 0;
                switch (num2)
                {
                    case 0:
                        b = 1;
                        break;
                    case 1:
                        b = 2;
                        break;
                    case 2:
                        b = 4;
                        break;
                    case 3:
                        b = 8;
                        break;
                    case 4:
                        b = 16;
                        break;
                    case 5:
                        b = 32;
                        break;
                    case 6:
                        b = 64;
                        break;
                    case 7:
                        b = 128;
                        break;
                }
                if ((InBytes[num] & b) == b)
                {
                    array[i] = true;
                }
            }
            return array;
        }
    }
}
